home *** CD-ROM | disk | FTP | other *** search
- unit FastObjects;
-
- interface
-
- type
- TInteger = class
- private
- FValue : Integer;
- public
- // Just calls DoCreate
- constructor Create( value : Integer );
- // Just calls DoDestroy
- destructor Destroy; override;
- property Value : Integer read FValue write FValue;
- protected
- // Performs all operations for Create, except allocating memory
- procedure DoCreate( value : Integer ); virtual;
- // Performs all operations for Destroy, except freeing memory
- procedure DoDestroy; virtual;
- end;
-
- TIntegerRec = record
- // This is just for the VMT all object have at the beginning
- _VMT : TClass;
- // The following members must have exactly the same size that
- // all members in TInteger have: this is easily accomplished by
- // copying all members in TInteger
- _FValue : Integer;
- end;
-
- TFastIntegerRec = record
- // This is just for the VMT all object have at the beginning
- _VMT : TClass;
- // The following members must have exactly the same size that
- // all members in TInteger have: this is easily accomplished by
- // copying all members in TInteger
- _FValue : Integer;
- end;
-
- // Equivalent to TInteger.Create, but uses the memory provided by rec,
- // so that a TIntegerRec in the stack can be used
- function CreateObject( var rec : TIntegerRec; value : Integer ): TInteger; overload;
- // Returns the TInteger allocated in rec: note that Create(rec, value)
- // must have been called previously.
- function GetObject( const rec : TIntegerRec ): TInteger; overload;
- // Subsitutes GetObject(rec).Free. In fact, this can't be called
- // because it would call FreeMem(@rec), which is not a good idea!
- procedure FreeObject( var rec : TIntegerRec ); overload;
-
- function CreateObject( var rec : TFastIntegerRec; value : Integer ): TInteger; overload;
- procedure FreeObject( var rec : TFastIntegerRec ); overload;
- function GetObject( const rec : TFastIntegerRec ): TInteger; overload;
-
- implementation
-
- function CreateObject( var rec : TIntegerRec; value : Integer ): TInteger;
- begin
- TInteger.InitInstance(@rec);
- Result := GetObject(rec);
- // We provide exactly the same semantics for Create(rec,value) as
- // for TInteger.Create(value): that means that the "destructor" must
- // be called if creation fails. Since DoCreate does all what Create
- // does, except memory allocation, and DoDestroy performs all what
- // Destroy does, except memory deallocation, we call them.
- try
- Result.DoCreate( value );
- Result.AfterConstruction;
- except
- Result.DoDestroy;
- Result.CleanupInstance;
- raise;
- end;
- end;
-
- procedure FreeObject( var rec : TIntegerRec );
- var
- obj : TInteger;
- begin
- obj := GetObject(rec);
- obj.BeforeDestruction;
- obj.DoDestroy;
- obj.CleanupInstance;
- end;
-
- function GetObject( const rec : TIntegerRec ): TInteger;
- begin
- Result := TInteger(@rec);
- end;
-
- function CreateObject( var rec : TFastIntegerRec; value : Integer ): TInteger;
- begin
- rec._VMT := TInteger;
- Result := TInteger(@rec);
- Result.FValue := value;
- end;
-
- procedure FreeObject( var rec : TFastIntegerRec ); overload;
- begin
- end;
-
- function GetObject( const rec : TFastIntegerRec ): TInteger;
- begin
- Result := TInteger(@rec);
- end;
-
- { TInteger }
-
- constructor TInteger.Create(value: Integer);
- begin
- DoCreate( value );
- end;
-
- procedure TInteger.DoCreate(value: Integer);
- begin
- FValue := value;
- end;
-
- destructor TInteger.Destroy;
- begin
- DoDestroy;
- end;
-
- procedure TInteger.DoDestroy;
- begin
- // Ok, we do nothing, but this is needed for demonstration purposes;
- end;
-
- {$ifdef DEBUG}
- initialization
- // Check that TIntegerRec has exactly the same size as a TInteger
- // instance
- Assert( SizeOf( TIntegerRec ) = TInteger.InstanceSize );
- // Check that TFastIntegerRec has exactly the same size as a TInteger
- // instance
- Assert( SizeOf( TFastIntegerRec ) = TInteger.InstanceSize );
- {$endif} // DEBUG
- end.
-